import 'dart:async';
import 'dart:io';

import 'package:bigegg/common/http/xmm_http.dart';
import 'package:bigegg/common/log/xmm_logcat.dart';
import 'package:bigegg/global/user/xmm_account_manager.dart';
import 'package:bigegg/global/xmm_apis.dart';
import 'package:bigegg/utils/xmm_platform_utils.dart';
import 'package:flutter/foundation.dart';

import '../../utils/xmm_md5_utils.dart';

/// 打点请求头key统一传参
class XmmLogHeadersKey {

  static const String logData = "data";
  static const String logLogType = "log_type";
  static const String logSubtype = "subtype";
  static const String logBehavior = "behavior";
  static const String logDeviceId = "device-id";
  static const String logAndroidId = "android_id";
  static const String logUserId = "user_id";
  static const String logPkg = "pkg";
  static const String logChnId = "chn_id";
  static const String logVer = "ver";
  static const String logPlatform = "platform";
  static const String logModel = "model";
  static const String logPVer = "p_ver";
  static const String logLanId = "lan_id";
  static const String logSecId = "sec_id";
  static const String logUtmSource = "utm_source";
  static const String logAfAdgroupId = "af_adgroup_id";
  static const String logAfAdset = "af_adset";
  static const String logAfAdsetId = "af_adset_id";
  static const String logAfStatus = "af_status";
  static const String logAfAgency = "af_agency";
  static const String logAfChannel = "af_channel";
  static const String logAfCampaign = "campaign";
  static const String logAfCampaignId = "campaign_id";
  static const String logCountry = "country";
  static const String logSysLan = "sys_lan";
}

/// 打点中所有涉及到的页面KEY
/// 1.启动页面埋点，page -- launch'
/// 2.登录页面埋点
/// a.快速登录，page--quicklogin
/// b.苹果登录，page --applelogin
/// c.用户协议，page -- 'terms'
/// d.隐私协议，page --privacy
/// e.登录成功，page-- loginsuccess'
/// 各主tab点击事件埋点3
/// 4.内购埋点
/// a.打开充值页面，page--"purchase'
/// b.创建内购订单，page --'createorder5.我的埋点
/// a编辑头像，page --editavatar'
/// b.退出登录，page--logout'
/// c，删除账号，page --deleteaccount'
/// d.点击客服，page --'customer
/// 6.其它
/// a.举报，page--'report'
/// b.拉黑，page--"block!
class XmmLogPages {
  static const String pageLaunch = 'launch';
  static const String pageQuickLogin = 'quicklogin';
  static const String pageAppleLogin = 'applelogin';
  static const String pageTerms = 'terms';
  static const String pagePrivacy = 'privacy';
  static const String pageLoginSuccess = 'loginsuccess';
  static const String pagePurchase = 'purchase';
  static const String pageCreateOrder = 'createorder';
  static const String pageEditAvatar = 'editavatar';
  static const String pageLogout = 'logout';
  static const String pageDeleteAccount = 'deleteaccount';
  static const String pageCustomer = 'customer';
  static const String pageReport = 'report';
  static const String pageBlock = 'block';
}

class XmmLogPvManger {
  XmmLogPvManger._();

  static const String _event = 'event';
  static const String _tm = 'tm';
  static const String _page = 'page';
  static const String _subPage = 'subPage';
  static const String _terPage = 'terPage';
  static const String _broadcasterId = 'broadcasterId';
  static const String _duration = 'duration';

  static void stat({
    String? page,
    String? subPage,
    String? terPage,
    String? broadcasterId,
  }) {
    var map = <String, dynamic>{};
    // ⚠️page传入下方的埋点事件page值
    if (page != null) {
      map[_page] = page;
    }
    if (subPage != null) {
      map[_subPage] = subPage;
    }
    if (terPage != null) {
      map[_terPage] = terPage;
    }
    if (broadcasterId != null) {
      map[_broadcasterId] = broadcasterId;
    }
    map[_duration] = 0;
    map[_event] = 'pv';
    map[_tm] = DateTime
        .now()
        .millisecondsSinceEpoch;

    if (kDebugMode) {
      XmmXLogcat.d('$map LogPvMgr');
    }
    XmmLogManger().putLog(XmmLogType.globalBehavior, map);
  }
}

/// 打点类型
enum XmmLogType {
  globalBehavior('event', 'global_behavior', 'event'),
  clickEvent("event", "click", "event");

  final String logType;
  final String subType;
  final String behavior;

  const XmmLogType(this.logType, this.subType, this.behavior);
}

// 打点管理
class XmmLogManger {
  static final XmmLogManger _instance = XmmLogManger._internal();

  factory XmmLogManger() {
    return _instance;
  }

  XmmLogManger._internal();

  static const String tag = "LogManger"; // 日志标签
  static const int limitSize = 20; // 打点任务最多缓存长度
  static int _serialId = 0;

  // 每次启动App该值会修改
  static String launcherId = XmmMD5Utils.getMd5('${DateTime
      .now()
      .millisecondsSinceEpoch}${XmmPlatformUtils.deviceId}');
  final List<Map<String, dynamic>> cacheList = [];
  bool _isWaitingForSend = false; // 是否需要延迟上报

  /// 上报日志
  void putLog(XmmLogType logType, Map<String, dynamic>? event) {
    if (logType.logType.isEmpty ||
        logType.subType.isEmpty ||
        logType.behavior.isEmpty ||
        event == null ||
        event.isEmpty) {
      return;
    }
    Map<String, dynamic> itemData = _buildItemData(
        logType.logType, logType.subType, logType.behavior, event);
    cacheList.insert(0, itemData);
    sendDelayed();
  }

  /// 延时发送日志
  void sendDelayed() {
    if (_isWaitingForSend) {
      return;
    }
    _isWaitingForSend = true;
    Timer(const Duration(milliseconds: 2000), () {
      _isWaitingForSend = false;
      sendLog(false);
    });
  }

  /// 发日志打点
  void sendLog(bool forceUploadAll) {
    try {
      List<Map<String, dynamic>> sendList = [];
      if (cacheList.isEmpty) {
        return;
      } else if (cacheList.length >= limitSize && !forceUploadAll) {
        sendList.addAll(cacheList.sublist(0, limitSize));
        cacheList.removeRange(0, limitSize);
      } else {
        sendList.addAll(cacheList);
        cacheList.clear();
      }
      _doUpload(sendList, true);
    } catch (e) {
      if (kDebugMode) {
        print(e);
      }
    }
  }

  /// 立马发送日志
  void putLogRightNow(XmmLogType logType, Map<String, dynamic>? event) {
    if (logType.logType.isEmpty ||
        logType.subType.isEmpty ||
        logType.behavior.isEmpty ||
        event == null ||
        event.isEmpty) {
      return;
    }
    Map<String, dynamic> itemData = _buildItemData(
        logType.logType, logType.subType, logType.behavior, event);
    List<Map<String, dynamic>> list = [];
    list.add(itemData);

    _doUpload(list, false);
  }

  /// 执行上传
  Future<void> _doUpload(List<Map<String, dynamic>> sendList,
      bool isContinue) async {
    XmmXHttpClient.instance().postResponse(
      XmmApis.logReport,
      formData: sendList,
    ).then((value) {
      if (isContinue) {
        sendDelayed();
      }
    });
  }

  Map<String, dynamic> _buildItemData(String logType, String subType,
      String behavior, Map<String, dynamic>? event) {
    String platform = '';
    String model = '';
    if (Platform.isAndroid) {
      platform = 'Android';
      model = XmmPlatformUtils.androidInfo?.hardware ?? '';
    } else if (Platform.isIOS) {
      platform = 'iOS';
      model = XmmPlatformUtils.iosInfo?.model ?? '';
    }
    Map<String, dynamic> itemData = {};
    itemData[XmmLogHeadersKey.logData] = [event];
    itemData[XmmLogHeadersKey.logLogType] = 'event';
    itemData[XmmLogHeadersKey.logSubtype] = 'global_behavior';
    itemData[XmmLogHeadersKey.logBehavior] = 'event';
    itemData[XmmLogHeadersKey.logDeviceId] = XmmPlatformUtils.deviceId;
    itemData[XmmLogHeadersKey.logUserId] = XmmAccountManager.instance.user.userId;
    itemData[XmmLogHeadersKey.logPkg] = XmmPlatformUtils.packageName;
    itemData[XmmLogHeadersKey.logChnId] = '';
    itemData[XmmLogHeadersKey.logVer] = XmmPlatformUtils.appVersionName;
    itemData[XmmLogHeadersKey.logPlatform] = platform;
    itemData[XmmLogHeadersKey.logModel] = model;
    itemData[XmmLogHeadersKey.logPVer] = XmmPlatformUtils.appVersionCode;
    itemData[XmmLogHeadersKey.logLanId] = launcherId;
    itemData[XmmLogHeadersKey.logSecId] = _serialId++;
    itemData[XmmLogHeadersKey.logSysLan] = XmmPlatformUtils.systemLanguage;
    itemData[XmmLogHeadersKey.logCountry] = XmmAccountManager.instance.user.country ?? '';
    itemData["tm"] = DateTime.now().millisecondsSinceEpoch;
    return itemData;
  }
}